module odefu.engine.states.State;

import odefu.engine.input.KeyEvent;

public interface State
{
	public void enter();
	
	public void exit();
	
	public void changeSubState(State subState);
	
	public bool allowStateChange(State state);
	
	public void update(float delta);
	
	public void draw(float delta);
	
	public void handleKeyEvent(KeyEvent event);
	
	@property
	{
		public Object param();
		public State subState();
	}
}

public abstract class AbstractState(T) : State
{
	private State _subState;
	
	private State nextState;
	
	private T _param;
	
	public this(T param = null)
	{
		_param = param;
	}
	
	@property
	{
		public override T param()
		{
			return _param;
		}
		
		public override State subState()
		{
			return _subState;
		}
	}
	
	public override void enter(T param = null)
	{
		_param = param;
	}
	
	public override void exit()
	{
		if (_subState)
		{
			_subState.exit();
			_subState = null;
		}
		_param = null;
		nextState = null;
	}
	
	public override void changeSubState(State subState)
	{
		if (_subState != subState && nextState != subState)
		{
			nextState = subState;
		}
	}
	
	public override void update(float delta)
	{
		if (nextState)
		{
			if (_subState)
			{
				_subState.exit();
			}
			_subState = nextState;
			_subState.enter();
			nextState = null;
		}
		
		if (_subState)
		{
			_subState.update(delta);
		}
	}
}
